
def test0():
    # 切片于直接赋值的区别

    list1 = [1, 2, 3, 4, 5]
    list1_copy = list1
    list1_copy[0] = 100

    list2 = [1, 2, 3, 4, 5]
    list2_slice = list2[:]
    list2_slice[0] = 100

    print(list1)
    print(list1_copy)
    print(list2)
    print(list2_slice)

    """
    [100, 2, 3, 4, 5]
    [100, 2, 3, 4, 5]
    [1, 2, 3, 4, 5]
    [100, 2, 3, 4, 5]
    """

def test1():

    # 可迭代对象 iterable
    for index,num in enumerate(range(100, 200)):
        print(f"{index=},and {num=}")

    # 可迭代函数
    print(sum(range(10)))

def test2():
    class Point:
        def __init__(self, x, y):
            self.x = x
            self.y = y

    def where_is(point):
        # match 中可以自动解包, x就是 Point 的变量可以直接读取
        match point:
            case Point(x=0, y=0):
                print("Origin")
            case Point(x=0, y=y):
                print(f"Y={y}")
            case Point(x=x, y=0):
                print(f"X={x}")
            case Point():
                print("Somewhere else")
            case _:
                print("Not a point")

    where_is(Point(0,10))

def test3():
    # 默认值是数组就会隐式共享,如果是None就不会
    def f(a, L=None):
        if L is None:
            L = []
        L.append(a)
        return L
    
    print(f(1))
    print(f(2))
    print(f(3))

def test4():
    def func(arg, *args):
        for str in args:
            print(str)

    # *args 形参会自动打包
    # 仅限位置形参的名称可以在 **kwds 中使用，而不产生歧义。  / 和 *
    func("hello","你好","测试","xxx")

def test5():
    # 解包实参列表
    args = [3, 6]
    var = list(range(*args))
    print(*var)

    # 解包实参字典,自动绑定key value
    def parrot(voltage, state='a stiff', action='voom'):
        print("-- This parrot wouldn't", action, end=' ')
        print("if you put", voltage, "volts through it.", end=' ')
        print("E's", state, "!")

    d = {"voltage": "four million", "state": "bleedin' demised", "action": "VOOM"}
    parrot(**d)

def test6() -> str:
    # 标准函数定义方案(约定俗成)
    def func(arg:int):
        """简要介绍这个函数的作用.

        可以添加附加说明
        
        arg:这是一个参数
        """
        pass
        return "func return var"

    """
    缩进，用 4 个空格，不要用制表符。
    制表符会引起混乱，最好别用。
    换行，一行不超过 79 个字符。
    这样换行的小屏阅读体验更好，还便于在大屏显示器上并排阅读多个代码文件。
    用空行分隔函数和类，及函数内较大的代码块。
    最好把注释放到单独一行。
    使用文档字符串。
    运算符前后、逗号后要用空格，但不要直接在括号内使用： a = f(1, 2) + g(3, 4)。
    类和函数的命名要一致；按惯例，命名类用 UpperCamelCase，命名函数与方法用 lowercase_with_underscores。
    命名方法中第一个参数总是用 self (类和方法详见 初探类)。
    编写用于国际多语环境的代码时，不要用生僻的编码。Python 默认的 UTF-8 或纯 ASCII 可以胜任各种情况。
    同理，就算多语阅读、维护代码的可能再小，也不要在标识符中使用非 ASCII 字符。
    """

def test7():
    # 无列表推导式
    # squares = []
    # for x in range(10):
    #     squares.append(x**2)

    squares = [x**2 for x in range(10)]

    print(squares)

    # 复杂案例 按左到右顺序
    var = [(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
    print(var)

def test8():
    # 数据类型
    # 1 数值类型:整数 浮点 复数
    # 2 布尔 
    # 3 序列类型 字符串 列表 元组( 不可变的列表,使用() )
    # 4 集合类型 集合 冻结集合 (frozenset)
    # 5 映射类型 字典( {"key":"value"} )
    # 6 二进制 字节( b'hello' ) 字节数组( bytearray(b'hello') )  内存视图 memoryview(b'hello')

    # 类型检查
    # type(10)        # <class 'int'>
    # isinstance(3.14, float)  # True
    pass

def test9():
    import fibo
    fibo.fib(1000)

    print(fibo.fib2(1000))

def test10():
    # format
    print("{}".format(100))
    print("{1} 顺序 {0}".format(100,99))
    print("{key1} {key2}".format(key1=100,key2="test"))
    info = {"key1":"value1", "key2":"value2"}
    print(">>> {key1} {key2}".format(**info))       # 字典需要解包
    print("数字格式 {:10.5f}".format(101.101))

    # f字符串
    pass

def test11():
    """
    文件操作
    """
    # with open("testFile.txt","a",encoding="utf-8") as f:
    #     for i in range(100):
    #         f.write("hello world\n")
        
    # with open("testFile.txt","r",encoding="utf-8") as f:
    #     for line in f:
    #         print(line, end='')
    
    #json
    import json
    data = [1, "test", {"key":"value"}]

    # with open("jsonData.json", "w") as f:
    #     json.dump(data, f) 

    with open("jsonData.json", "r") as f:

        data_copy = json.load(f)
        if data_copy == data:
            print("==")

        print(data_copy)

def test12():
    """
    异常链
    """
    # try:
    #     open("database.sqlite")
    # except OSError:
    #     raise RuntimeError("unable to handle error")
    # finally:
    #     print("end")  
    
    # 异常转换
    def func():
        raise ConnectionError

    try:
        func()
    except ConnectionError as exc:
        raise RuntimeError('Failed to open database') from exc
        
# def test13():
def scope_test():
    def do_local():
        spam = "local spam"

    def do_nonlocal():
        nonlocal spam
        spam = "nonlocal spam"

    def do_global():
        # global 会在没有全局变量时定义到全局上去
        global spam
        spam = "global spam"

    spam = "test spam"
    do_local()
    print("After local assignment:", spam)
    do_nonlocal()
    print("After nonlocal assignment:", spam)
    do_global()
    print("After global assignment:", spam)

scope_test()
print("In global scope:", spam)

if __name__ == "__main__":
    pass
    # test12()